package com.yq.testmodule.recycleview

import androidx.recyclerview.widget.RecyclerView
import androidx.recyclerview.widget.RecyclerView.LayoutManager
import androidx.recyclerview.widget.RecyclerView.LayoutParams
import androidx.recyclerview.widget.RecyclerView.Recycler
import com.fmt.mvi.learn.gobal.log

class CustomLayoutManager : LayoutManager() {

    //y轴偏移量
    private var mOffsetY = 0

    override fun generateDefaultLayoutParams(): RecyclerView.LayoutParams {
        return RecyclerView.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)
    }

    override fun onMeasure(
        recycler: RecyclerView.Recycler,
        state: RecyclerView.State,
        widthSpec: Int,
        heightSpec: Int
    ) {
        super.onMeasure(recycler, state, widthSpec, heightSpec)
    }


    override fun onLayoutChildren(recycler: RecyclerView.Recycler, state: RecyclerView.State) {
        super.onLayoutChildren(recycler, state)
        if (state.itemCount == 0) {
            removeAndRecycleAllViews(recycler)
            return
        }
        //暂时分离和回收有效item
        detachAndScrapAttachedViews(recycler)
        var top = paddingTop
        //开始布局,布局至屏幕可见范围
        for (i in 0 until state.itemCount) {
            //根据postion 获取view
            val itemView = recycler.getViewForPosition(i)
            //添加进去，当然里面不一定每次都是调用RecyclerView的addView方法的，
            //如果是从缓存区里面找到的，只需调用attachView方法把它重新连接上就行了。
            addView(itemView)
            //测量item，当然，也不是每次都会调用measure方法进行测量的，
            //它里面会判断，如果已经测量过，而且当前尺寸又没有收到更新的通知，就不会重新测量。
            measureChildWithMargins(itemView, 0, 0)
            val left = paddingLeft
            val right = left + getDecoratedMeasuredWidth(itemView)
            val bottom = top + getDecoratedMeasuredHeight(itemView)
            layoutDecorated(itemView, left, top, right, bottom)
            if (bottom > height - paddingBottom) {
                break
            }
            top = bottom
        }

    }

    override fun canScrollVertically(): Boolean {
        return true
    }


    var mLastOffset = 0
    override fun scrollVerticallyBy(
        dy: Int,
        recycler: RecyclerView.Recycler,
        state: RecyclerView.State
    ): Int {
        if (dy == 0 || itemCount == 0) {
            return 0
        }
        var mDy = dy
        //滚动过程中 填充头或者尾view
        fillVertical(recycler, mDy > 0)
        mLastOffset = mOffsetY
        updateOffsetY(mDy)
        mDy = mOffsetY - mLastOffset
        //滚动view
        offsetChildrenVertical(-mDy)
        //回收view
        recyclerChildView(mDy > 0, recycler)
        return mDy
    }
    //累加y轴偏移量
    private fun updateOffsetY(dy: Int) {
        mOffsetY += dy
        if(mOffsetY < 0){
            mOffsetY = 0
        }
        //向上滑动 判断最后一个是否滑动到底部
        if(dy>0){
            //获取最后一个view
            val lastView = getChildAt(childCount - 1) ?: return
            //获取该view的postion
            val lastViewPosition = getPosition(lastView)
            //判断是否滑动到底部
            if (lastViewPosition == itemCount - 1) {
                //获取最后一个view的底部
                val lastViewBottom = getDecoratedBottom(lastView)
                //判断是否滑动到底部，如果超出，修正
                if(lastViewBottom - dy <= height - paddingBottom){
                    mOffsetY -= dy;
                    mOffsetY  +=lastViewBottom - (height - paddingBottom)
                }
            }
        }
    }

    //回收
    private fun recyclerChildView(fillEnd: Boolean, recycler: Recycler) {
        if (fillEnd) {
            //回收头部
            for (i in 0 until childCount) {
                val view = getChildAt(i) ?: return
                if (getDecoratedBottom(view) < paddingTop) {
                    removeAndRecycleView(view, recycler)
                } else {
                    break
                }
            }
        } else {
            //回收尾部
            for (i in childCount - 1 downTo 0) {
                val view = getChildAt(i) ?: return
                if (getDecoratedTop(view) > height - paddingBottom) {
                    removeAndRecycleView(view, recycler)
                } else {
                    break
                }
            }
        }
    }

    private fun fillVertical(recycler: Recycler, fillEnd: Boolean) {
        if (fillEnd) {
            //填充尾部
            var lastView = getChildAt(childCount - 1) ?: return
            var lastViewBottom = getDecoratedBottom(lastView)
            while (lastViewBottom < height - paddingBottom) {
                val lastViewPosition = getPosition(lastView)
                if (lastViewPosition == itemCount - 1) {
                    break
                }
                val view = recycler.getViewForPosition(lastViewPosition + 1)
                addView(view)
                measureChildWithMargins(view, 0, 0)
                val left = paddingLeft
                val right = left + getDecoratedMeasuredWidth(view)
                val top = lastViewBottom
                val bottom = top + getDecoratedMeasuredHeight(view)
                layoutDecorated(view, left, top, right, bottom)
                lastViewBottom = bottom
                lastView = view
            }

        } else {
            //填充头部
            var firstView = getChildAt(0) ?: return
            var firstViewTop = getDecoratedTop(firstView)
            while (firstViewTop > paddingTop) {
                val firstViewPosition = getPosition(firstView)
                if (firstViewPosition == 0) {
                    break
                }
                val view = recycler.getViewForPosition(firstViewPosition - 1)
                addView(view, 0)
                measureChildWithMargins(view, 0, 0)
                val left = paddingLeft
                val right = left + getDecoratedMeasuredWidth(view)
                val bottom = firstViewTop
                val top = bottom - getDecoratedMeasuredHeight(view)
                layoutDecorated(view, left, top, right, bottom)
                firstViewTop = top
                firstView = view
            }
        }
    }


}